package com.luoling.shell;

import com.luoling.zipRead.ZipRead;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

/**
 * Description:
 * Copyright:   Copyright (c)2024
 * Company:
 *
 * @author: 张李鑫
 * @version: 1.0
 * Create at:   2024-05-29 17:19:22
 * <p>
 * Modification History:
 * Date         Author      Version     Description
 * ------------------------------------------------------------------
 * 2024-05-29     张李鑫                     1.0         1.0 Version
 */

public abstract class Shell implements Execute {
    private static final Logger log = LoggerFactory.getLogger(Shell.class);
    private String commandPrefix;


    private HashMap<String, String> params;

    private List<String> commands;

    private String format;

    private Process process;

    private ProcessBuilder processBuilder;

    private Execute execute;

    protected BufferedReader bufferedReader;

    public Shell() {
    }


    abstract String buildCommand();


    public boolean process() throws Exception {
        return execute.execute();
    }

    public Shell(String commandPrefix, HashMap<String, String> params) {
        this.commandPrefix = commandPrefix;
        this.params = params;
        this.commands = new ArrayList<>();
        String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
        boolean isWindows = os.contains("windows");
        this.commands.add(isWindows ? "cmd.exe" : "bash");
        this.commands.add(isWindows ? "/c" : "-c");
        this.format = isWindows ? "GBK" : "UTF-8";
        this.processBuilder = new ProcessBuilder();

        this.execute = (Execute) Proxy.newProxyInstance(
                this.getClass().getClassLoader(),
                new Class[]{Execute.class},
                new CloseStream(this)
        );
    }

    public Process start() throws IOException {
        processBuilder.redirectErrorStream(true);
        this.commands.add(buildCommand());
        processBuilder.command(this.commands);
        processBuilder.directory(new File(this.params.get("directory")+File.separator));
        this.process = processBuilder.start();
        return process;
    }


    public String getCommandPrefix() {
        return commandPrefix;
    }

    public void setCommandPrefix(String commandPrefix) {
        this.commandPrefix = commandPrefix;
    }

    public HashMap<String, String> getParams() {
        return params;
    }

    public void setParams(HashMap<String, String> params) {
        this.params = params;
    }

    public List<String> getCommands() {
        return commands;
    }

    public void setCommands(List<String> commands) {
        this.commands = commands;
    }

    public String getFormat() {
        return format;
    }

    public void setFormat(String format) {
        this.format = format;
    }

    public Process getProcess() {
        return process;
    }

    public void setProcess(Process process) {
        this.process = process;
    }

    public ProcessBuilder getProcessBuilder() {
        return processBuilder;
    }

    public void setProcessBuilder(ProcessBuilder processBuilder) {
        this.processBuilder = processBuilder;
    }

    public Execute getExecute() {
        return execute;
    }

    public void setExecute(Execute execute) {
        this.execute = execute;
    }

    public BufferedReader getBufferedReader() {
        return bufferedReader;
    }

    public void setBufferedReader(BufferedReader bufferedReader) {
        this.bufferedReader = bufferedReader;
    }

    /**
     * 修复print 方法 不在try里声明
     * 流的关闭统一由closeStreams来执行
     */
    public void print() {
        InputStream inputStream = null;
        InputStreamReader in = null;
        BufferedReader reader = null;
        try {
            inputStream = this.process.getInputStream();
            in = new InputStreamReader(inputStream);
            reader = new BufferedReader(in);
            String line;
            while ((line = reader.readLine()) != null) {
                // 在这里根据输出结果来进行判断
                log.error(line);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    public void closeStreams() {
        log.info("closeStreams command:{}", buildCommand());
        if (this.process != null) {
            try {
                this.process.getInputStream().close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
            try {
                this.process.getOutputStream().close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
            try {
                this.process.getErrorStream().close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
            try {
                this.bufferedReader.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
    }
}



